package br.com.gkarian.mydesk.services.financeiro;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.caelum.vraptor.ioc.Component;
import br.com.gkarian.mydesk.dao.financeiro.interfaces.BancoDAO;
import br.com.gkarian.mydesk.dao.financeiro.interfaces.ContaBancariaDAO;
import br.com.gkarian.mydesk.formatter.ValorFormatter;
import br.com.gkarian.mydesk.model.Usuario;
import br.com.gkarian.mydesk.model.financeiro.Banco;
import br.com.gkarian.mydesk.model.financeiro.ContaBancaria;
import br.com.gkarian.mydesk.model.financeiro.Transacao;
import br.com.gkarian.mydesk.services.financeiro.interfaces.ContaBancariaService;
import br.com.gkarian.mydesk.services.interfaces.UsuarioService;

@Component
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public class ContaBancariaServiceImpl implements ContaBancariaService {

	private static final Logger LOG = Logger
			.getLogger(ContaBancariaServiceImpl.class);

	private BancoDAO bancoDao;
	private ContaBancariaDAO contaBancariaDao;
	private UsuarioService usuarioService;
	private ValorFormatter valorFormatter;

	public ContaBancariaServiceImpl(BancoDAO bancoDao, UsuarioService usuarioService,
			ContaBancariaDAO contaBancariaDao) {
		this.bancoDao = bancoDao;
		this.contaBancariaDao = contaBancariaDao;
		this.usuarioService = usuarioService;
		this.valorFormatter = new ValorFormatter();
	}

	@Override
	public ContaBancaria cadastrarContaBancaria(ContaBancaria contaBancaria,
			Integer bancoId, Usuario usuario) throws Exception {
		LOG.info("Cadastrando ContaBancaria no Banco de ID [" + bancoId
				+ "] para o Usuario com ID [" + usuario.getId() + "]");
		Banco banco = bancoDao.carregar(bancoId);
		contaBancaria.setSaldo(valorFormatter.removerPontuacao(contaBancaria
				.getSaldo()));
		contaBancaria.setBanco(banco);
		contaBancaria.setUsuario(usuario);
		contaBancaria = contaBancariaDao.salvar(contaBancaria);
		LOG.info("ContaBancaria de ID [" + contaBancaria.getId()
				+ "] cadastrada com sucesso no Banco de ID [" + bancoId
				+ "] para o Usuario de ID [" + usuario.getId() + "]");
		return contaBancaria;
	}

	@Override
	public List<ContaBancaria> listarContasBancarias(Usuario usuario)
			throws Exception {
		LOG.info("Listando ContasBancarias do Usuario de ID ["
				+ usuario.getId() + "]");
		List<ContaBancaria> listContasBancarias = usuarioService
				.carregarComListContaBancaria(usuario).getListContasBancarias();
		LOG.info("Foram recuperadas " + listContasBancarias.size()
				+ " contasBancarias do Usuario de ID [" + usuario.getId() + "]");
		return listContasBancarias;
	}

	@Override
	public ContaBancaria carregarContaBancaria(Integer contaBancariaId)
			throws Exception {
		LOG.info("Recuperando ContaBancaria de ID [" + contaBancariaId + "]");
		ContaBancaria contaBancaria = contaBancariaDao
				.carregar(contaBancariaId);
		LOG.info("ContaBancaria de ID [" + contaBancaria.getId()
				+ "] recuperada com sucesso");
		return contaBancaria;
	}

	@Override
	public void removerContaBancaria(ContaBancaria contaBancaria)
			throws Exception {
		LOG.info("Removendo ContaBancaria de ID [" + contaBancaria.getId()
				+ "]");
		// TODO: Verificar se a ContaBancaria eh do Usuario logado
		contaBancariaDao.remover(contaBancaria);
		LOG.info("ContaBancaria de ID [" + contaBancaria.getId()
				+ "] removida com sucesso");
	}

	@Override
	public void removerContaBancaria(Integer id) throws Exception {
		LOG.info("Removendo ContaBancaria de ID [" + id + "]");
		// TODO: Verificar se a ContaBancaria eh do Usuario logado
		ContaBancaria contaBancaria = contaBancariaDao.carregar(id);
		contaBancariaDao.remover(contaBancaria);
		LOG.info("ContaBancaria de ID [" + contaBancaria.getId()
				+ "] removida com sucesso");
	}

	@Override
	public void atualizarContaBancaria(ContaBancaria contaBancaria,
			Integer bancoId, Usuario usuario) throws Exception {
		LOG.info("Atualizando ContaBancaria de ID [" + contaBancaria.getId()
				+ "] pertencente ao Banco de ID [" + bancoId
				+ "] para o Usuario de ID [" + usuario.getId() + "]");
		Banco banco = bancoDao.carregar(bancoId);
		contaBancaria.setSaldo(valorFormatter.removerPontuacao(contaBancaria
				.getSaldo()));
		contaBancaria.setBanco(banco);
		contaBancaria.setUsuario(usuario);
		contaBancariaDao.atualizar(contaBancaria);
		LOG.info("ContaBancaria de ID [" + contaBancaria.getId()
				+ "] pertencente ao Banco de ID [" + bancoId
				+ "] do Usuario de ID [" + usuario.getId()
				+ "] atualizado com sucesso");
	}

	@Override
	public void atualizarContaBancaria(ContaBancaria contaBancaria)
			throws Exception {
		LOG.info("Atualizando ContaBancaria de ID [" + contaBancaria.getId()
				+ "]");
		contaBancariaDao.atualizar(contaBancaria);
		LOG.info("ContaBancaria de ID [" + contaBancaria.getId()
				+ "] atualizado com sucesso");
	}

	@Override
	public String atualizarSaldoContaBancaria(Integer idContaBancaria,
			Usuario usuario) throws Exception {

		LOG.info("Atualizando saldo geral da ContaBancaria de ID ["
				+ idContaBancaria + "] do Usuario de ID [" + usuario.getId()
				+ "]");

		// recuperar contaBancaria
		boolean encontrou = false;
		List<ContaBancaria> listContasBancarias = usuarioService
				.carregarComListContaBancaria(usuario).getListContasBancarias();
		for (ContaBancaria cb : listContasBancarias) {
			if (cb.getId() == idContaBancaria) {
				encontrou = true;
				break;
			}
		}

		if (!encontrou) {
			LOG.info("Usuario de ID ["
					+ usuario.getId()
					+ "] não encontrado para atualização geral de saldo para a ContaBancaria de ID ["
					+ idContaBancaria + "]");
			throw new IllegalArgumentException(
					"Id passado não pertence ao Usuário!"); // TODO
		}

		// recuperar transacoes
		ContaBancaria contaBancaria = contaBancariaDao
				.carregarComListTransacoes(idContaBancaria);

		// soma valor total das transacoes
		long valorTotal = 0;
		for (Transacao transacao : contaBancaria.getListTransacao()) {
			if (transacao.isEntrada()) {
				valorTotal += Long.parseLong(transacao.getValor());
			} else {
				valorTotal -= Long.parseLong(transacao.getValor());
			}
		}

		String total = String.valueOf(valorTotal);

		// altera saldo da contaBancaria
		contaBancaria.setSaldo(total);

		// atualiza contaBancaria
		atualizarContaBancaria(contaBancaria);

		LOG.info("Saldo geral da ContaBancaria de ID [" + idContaBancaria
				+ "] do Usuario de ID [" + usuario.getId()
				+ "] atualizado com sucesso");

		return total;
	}
}
